%{
    #include <stdio.h>
    #include <iostream>
    #include <vector>

    extern int yylineno;
    extern int yylex();

    void yyerror(char *s) {
      fprintf (stderr, "%s\n", s);
    }
    #define YYPRINT(file, type, value) fprintf(file, "%d", value);

typedef std::string s_t;

class Target {
public:
    Target() {
        list = new std::vector<s_t>();
    }

    Target(const s_t &str) {
	list = new std::vector<s_t>();
        add(str);
    }
    
    void add(const s_t &str) {
        list->push_back(str);
    }

    void merge(const Target *other) {
        for (auto pos = list->begin(), e = list->end(); pos != e; ++pos)
            add(*pos);
    }
    
    
    Target* process(Target *dst, const s_t &prefix, const Target *postfix) {
        for (auto postPos = postfix->list->begin(), postEnd = postfix->list->end();
                 postPos != postEnd; 
                 ++postPos ) {
            for (auto pos = list->begin(), e = list->end(); pos != e; ++pos) {                
                dst->add(prefix + *pos + *postPos);
            } // foreach list
        } // foreach postfix
        return dst;
    }

    void print() {
        for (auto pos = list->begin(), e = list->end(); pos != e; ++pos)
            std::cout << *pos;
    }

    virtual ~Target() {
        delete list;
    }
private:
    std::vector<s_t> *list;
};


typedef struct {
    s_t str;
    Target *target;
} YYSTYPE;

#define YYSTYPE YYSTYPE

%}

%token NEWLINE 
%token SBEGIN SEND 
%token UNIONBEGIN UNIONEND
%token SLASH
%token STRING
%token TEXT

%type<str> TEXT STRING ITEM
%type<target> FULL TARGET

%%

FULL: 	TARGET {
		$1->print();
                delete $1;
	};

TARGET:   ITEM { $$ = new Target($1); }
	| ITEM TARGET { $$ = new Target($1); $$->merge($2); delete $2; }
	| ITEM SBEGIN TARGET SEND TARGET { $$ = $3->process(new Target(), $1, $5); delete $3; delete $5; }
	| ITEM UNIONBEGIN TARGET UNIONEND TARGET {}
; // TARGET 

ITEM:   { $$ = ""; }
	| TEXT ITEM { $$ = std::string($1) + $2; }
	| STRING ITEM { $$ = "\"" + std::string($1) + "\"" + $2; }
	| NEWLINE  { std::cout << "new" << std::endl; }
; // ITEM


%%
int main () { return yyparse(); }


